# Type Check 插件

import { SourceCode } from 'rspress/theme';

<SourceCode href="https://github.com/web-infra-dev/rsbuild/tree/main/packages/plugin-type-check" />

Type Check 插件提供在单独的进程中运行 TypeScript 类型检查的能力，插件内部集成了 [fork-ts-checker-webpack-plugin](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin)。

## 介绍

`fork-ts-checker-webpack-plugin` 的类型检查逻辑与 TypeScript 原生的 `tsc` 命令基本一致，它会自动读取 `tsconfig.json` 中的配置项，也可以通过 Type Check 插件提供的配置项来修改默认行为。

插件在开发环境和生产环境下的行为有以下差异：

- 在开发环境构建时，类型错误不会阻塞构建流程，只会在 terminal 中输出错误日志。
- 在生产环境构建时，类型错误会导致构建失败，以保证生产环境代码的稳定性。

## 快速开始

### 安装插件

你可以通过如下的命令安装插件:

import { PackageManagerTabs } from '@theme';

<PackageManagerTabs command="add @rsbuild/plugin-type-check -D" />

### 注册插件

你可以在 `rsbuild.config.ts` 文件中注册插件：

```ts title="rsbuild.config.ts"
import { pluginTypeCheck } from '@rsbuild/plugin-type-check';

export default {
  plugins: [pluginTypeCheck()],
};
```

### 配置 tsconfig.json

Type Check 插件默认基于当前项目根目录的 `tsconfig.json` 进行检查，下面是一份 `tsconfig.json` 文件的例子，你也可以根据项目的需求进行调整。

```json title="tsconfig.json"
{
  "compilerOptions": {
    "target": "ES2020",
    "lib": ["DOM", "ES2020"],
    "module": "ESNext",
    "strict": true,
    "skipLibCheck": true,
    "isolatedModules": true,
    "resolveJsonModule": true,
    "moduleResolution": "bundler"
  },
  "include": ["src"]
}
```

注意 `tsconfig.json` 中的字段并不会影响 Rsbuild 的编译行为和产物，只会影响类型检查的结果。

## 选项

### enable

是否开启 TypeScript 类型检查。

- **类型：** `boolean`
- **默认值：** `true`
- **示例：**

禁用 TypeScript 类型检查：

```js
pluginTypeCheck({
  enable: false,
});
```

仅在生产环境构建时开启类型检查：

```js
pluginTypeCheck({
  enable: process.env.NODE_ENV === 'production',
});
```

仅在开发环境构建时开启类型检查（不建议在生产环境构建时禁用类型检查，这会导致生产代码的稳定性下降）：

```js
pluginTypeCheck({
  enable: process.env.NODE_ENV === 'development',
});
```

### forkTsCheckerOptions

修改 `fork-ts-checker-webpack-plugin` 的选项，请参考 [fork-ts-checker-webpack-plugin - README](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin#readme) 了解可用选项。

- **类型：** `Object | Function`
- **默认值：**

```ts
const defaultOptions = {
  typescript: {
    // set 'readonly' to avoid emitting tsbuildinfo,
    // as the generated tsbuildinfo will break fork-ts-checker
    mode: 'readonly',
    // enable build when using project reference
    build: useReference,
    // avoid OOM issue
    memoryLimit: 8192,
    // use tsconfig of user project
    configFile: tsconfigPath,
    // use typescript of user project
    typescriptPath: require.resolve('typescript'),
  },
  issue: {
    // ignore types errors from node_modules
    exclude: [({ file = '' }) => /[\\/]node_modules[\\/]/.test(file)],
  },
  logger: {
    log() {
      // do nothing
      // we only want to display error messages
    },
    error(message: string) {
      console.error(message.replace(/ERROR/g, 'Type Error'));
    },
  },
};
```

#### Object 类型

当 `forkTsCheckerOptions` 的值为 Object 类型时，会与默认配置进行深层合并。

```ts
pluginTypeCheck({
  forkTsCheckerOptions: {
    issue: {
      exclude: [({ file = '' }) => /[\\/]some-folder[\\/]/.test(file)],
    },
  },
});
```

#### Function 类型

当 `forkTsCheckerOptions` 的值为 Function 类型时，默认配置会作为第一个参数传入，你可以直接修改配置对象，也可以返回一个对象作为最终配置。

```ts
pluginTypeCheck({
  forkTsCheckerOptions(options) {
    options.async = false;
    return options;
  },
});
```

## 注意事项

- 如果项目开启了 `ts-loader`，并且手动配置了 `compileOnly: false`，请关闭 Type Check 插件，避免重复类型检查。
- 在 VS Code 等 IDE 中会将部分 error 显示成 warning，但在 `fork-ts-checker-webpack-plugin` 检查中仍会显示为 error，详情可参考：[Why are some errors reported as warnings?](https://code.visualstudio.com/docs/typescript/typescript-compiling#_why-are-some-errors-reported-as-warnings)。

## 性能优化

类型检查的性能开销较大，你可以参考 TypeScript 官方的 [Performance 指南](https://github.com/microsoft/TypeScript/wiki/Performance) 来优化性能。

比如，正确配置 `tsconfig.json` 的 `include` 和 `exclude` 范围，可以有效较少不必要的类型检查，提升 TypeScript 性能：

```json title="tsconfig.json"
{
  "include": ["src"],
  "exclude": ["**/node_modules", "**/.*/"]
}
```

## Vue 组件

`fork-ts-checker-webpack-plugin` 不支持检查 `.vue` 组件中的 TypeScript 代码，你可以通过以下方式检查 `.vue` 文件的类型问题：

1. 安装 [vue-tsc](https://github.com/vuejs/language-tools/tree/master/packages/tsc) 包，它提供了 `.vue` 文件类型检查的能力。

<PackageManagerTabs command="add vue-tsc -D" />

2. 在 package.json 的 `build` 脚本中添加 `vue-tsc --noEmit` 命令：

```diff title="package.json"
{
  "scripts": {
-   "build": "rsbuild build"
+   "build": "vue-tsc --noEmit && rsbuild build"
  }
}
```

3. 由于生产构建使用 `vue-tsc` 进行类型检查，你可以在生产环境关闭 Type Check 插件，避免重复执行检查。

```js
pluginTypeCheck({
  enable: process.env.NODE_ENV === 'development',
});
```
